import yaml
import os
from Base.Base import Base
from selenium.webdriver.common.by import By
from typing import Tuple, Optional
class ApiClient():
    def __init__(self,config_path=None):
        self.config=self.load_config()
        self.base_url=self.config['api_base_url']

        self.base=Base

        """
                初始化加载器并加载配置文件
                :param config_path: 定位符配置文件路径
                """
        if config_path is None:
            config_path = self.load_location()
        self.config_path = config_path
        self.loc_config = self._load_config()

        # 支持的定位方式映射表（扩展时只需添加新的映射）
        self.supported_bys = {
            "ID": By.ID,
            "XPATH": By.XPATH,
            "CSS_SELECTOR": By.CSS_SELECTOR,
            "CLASS_NAME": By.CLASS_NAME,
            "TAG_NAME": By.TAG_NAME,
            "LINK_TEXT": By.LINK_TEXT,
            "PARTIAL_LINK_TEXT": By.PARTIAL_LINK_TEXT,
            "NAME": By.NAME
        }

    # 读取 config  配置文件的方法
    def load_config(self):
        # 获取文件夹路径
        current_dir = os.path.dirname(os.path.abspath(__file__))
        # 文件夹路径 拼接文件
        config_path = os.path.join(current_dir, '../Config/config.yaml')
        with open(config_path, 'r', encoding='utf-8') as f:
            # 使用yaml中安全的读取方法，防止sql 语句的注入
            return yaml.safe_load(f)

    def set_config_url(self,endpoint):
        url=self.base_url+endpoint
        return url
    def set_config(self,config_dict=None,**kwargs):
        if config_dict is None:
            config_dict = self.config

        try:
            result=config_dict
            for key in kwargs.get("keys",[kwargs]):
                result=result[key]
            return result
        except KeyError as e:
            print(f"配置服务哦")


    # 链接数据库
    def connent_db(self):
        config=self.config['database']
        return config

    # 读取 location.yaml 文件
    def load_location(self):
        # 获取当前文件所在路径
        current_dir = os.path.dirname(os.path.abspath(__file__))
        # 目标文件所在路径
        location_path = os.path.join(current_dir, '../Config/location.yaml')
        # # 处理../，转换为规范的绝对路径
        location_path = os.path.normpath(location_path)
        return location_path
        # print("路径"+location_path)
        # with open(location_path, 'r', encoding='utf-8') as f:
        #     return yaml.safe_load(f)

    # def set_location(self,config_dict=None,**kwargs):
    #     if config_dict is None:
    #         config_dict=self.load_location()
    #     try:
    #         result=config_dict
    #         for key in kwargs.get("keys",[kwargs]):
    #             result=result[key]
    #         return result
    #     except KeyError as e:
    #         print(f"配置服务哦")

        """元素定位符加载器，负责从配置文件解析定位信息"""



    def _load_config(self) -> dict:
        """加载并解析 YAML 配置文件"""
        try:
            with open(self.config_path, 'r', encoding='utf-8') as f:
                return yaml.safe_load(f) or {}  # 处理空文件
        except FileNotFoundError:
            raise FileNotFoundError(f"配置文件不存在: {self.config_path}")
        except yaml.YAMLError as e:
            raise ValueError(f"配置文件格式错误: {str(e)}")

    def get_locator(self, config_key: str, locator_key: str) -> Tuple[str, str]:
        """
        获取元素定位符（By类型 + 定位表达式）
        :param config_key: 配置分组键（如 "auth"）
        :param locator_key: 定位符键（如 "username_loc"）
        :return: (By常量, 定位表达式)
        """
        # 1. 从配置中获取定位信息
        group_config = self.loc_config.get(config_key)
        if not group_config:
            raise KeyError(f"配置分组不存在: {config_key}")

        locator_info = group_config.get(locator_key)
        if not locator_info:
            raise KeyError(f"定位符不存在: {config_key}.{locator_key}")

        # 2. 校验定位信息格式
        if not isinstance(locator_info, dict) or "by" not in locator_info or "location" not in locator_info:
            raise ValueError(f"定位符配置格式错误: {config_key}.{locator_key}，需包含 'by' 和 'location'")

        # 3. 转换定位方式为 By 常量
        by_type = locator_info["by"].upper()  # 统一转为大写，兼容大小写输入
        if by_type not in self.supported_bys:
            raise ValueError(f"不支持的定位方式: {by_type}，支持的方式: {list(self.supported_bys.keys())}")

        return self.supported_bys[by_type], locator_info["location"]

    def reload_config(self) -> None:
        """重新加载配置文件（用于动态更新配置时）"""
        self.loc_config = self._load_config()